﻿using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Drawing;
using System.Drawing.Imaging;
using System.Windows.Forms;
using CloudShot.ImageStorages;
using CloudShot.Properties;
using CloudShot.Utils;

namespace CloudShot
{
	public partial class MainForm : Form
	{
		private const int RECENT_LIST_SIZE = 10;

		private readonly GlobalHotListener _hotkeyListener;
		private readonly AppSettings _appSettings = new AppSettings();

		private IImageStorage _imageStorage;
		private Hotkey _hotkeyShot;
		private bool _isShottingStarted = false;

		private string ProductAndVersion { get { return Application.ProductName + " " + Application.ProductVersion; } }

		public MainForm()
		{
			InitializeComponent();
			
			_hotkeyListener = new GlobalHotListener(this);

			this.Icon = Resources.applicationIcon;
			treeIcon.Icon = Resources.applicationIcon;
			treeIcon.Text = ProductAndVersion;
		}

		private void OnLoad(object sender, EventArgs e)
		{
			this.Visible = false;

			_imageStorage = CreateStorage();
			ClearHotkey();
			SetupHotkey();
			FillRecentShots(_appSettings.RecentShotsList);

			treeIcon.Visible = true;
		}

		private IImageStorage CreateStorage()
		{
			//return new NivalImageStorage();

			if (_appSettings.PathToSave.Contains(DropboxUtils.DropboxPublicFolder))
			{
				return new DropboxImageStorage(_appSettings.PathToSave);
			}

			return new ImageStorage(_appSettings.PathToSave);
		}

		private void SetupHotkey()
		{
			if (!Hotkey.TryParse(_appSettings.ShotHotkey, out _hotkeyShot))
			{
				_hotkeyShot = new Hotkey(KeyModifiers.None, Keys.PrintScreen);
				_appSettings.ShotHotkey = _hotkeyShot.ToString();
			}

			if (!_hotkeyListener.Add(_hotkeyShot))
			{
				MessageBox.Show(string.Format("Hotkey \"{0}\" used by another application.\nPlease select another hotkey.", _hotkeyShot),
					Application.ProductName, MessageBoxButtons.OK, MessageBoxIcon.Exclamation);
				ShowSettings();
				return;
			}

			_hotkeyShot.HotkeyPressed += OnShot;
			mnuShot.ShortcutKeyDisplayString = _hotkeyShot.ToString();
			treeIcon.Text = ProductAndVersion + Environment.NewLine + "Горячая клавиша: " + _hotkeyShot.ToString();
		}

		private void ClearHotkey()
		{
			//удаляем старые хоткеи, если они уже были заданы
			if (_hotkeyShot != null)
			{
				_hotkeyShot.HotkeyPressed -= OnShot;
				_hotkeyListener.Remove(_hotkeyShot);
			}
		}

		private void FillRecentShots(IList<ShotInfo> shots)
		{
		//	mnuRecentShots.DropDownItems.Clear();

			for (int i = shots.Count - 1; i >= 0; --i)
			{
				ShotInfo recentShot = shots[i];

				if (!_imageStorage.IsShotInStorege(recentShot))
					continue;

				ToolStripMenuItem menuItem = new ToolStripMenuItem();
				menuItem.ImageScaling = ToolStripItemImageScaling.None;

				menuItem.Text = recentShot.Name;
				menuItem.Click += (s, a) => OpenInViewer(recentShot);
				menuItem.Image = recentShot.Thumbnail;
			//	mnuRecentShots.DropDownItems.Add(menuItem);
			}

			//mnuRecentShots.Enabled = mnuRecentShots.DropDownItems.Count > 0;
		}

		private void AddRecentShot(ShotInfo shotInfo)
		{
			List<ShotInfo> shots = new List<ShotInfo>(_appSettings.RecentShotsList);
			shots.RemoveAll(x => !_imageStorage.IsShotInStorege(x));

			shots.Add(shotInfo);

			if (shots.Count > RECENT_LIST_SIZE)
			{
				while (shots.Count > RECENT_LIST_SIZE)
				{
					shots.RemoveAt(0);
				}
			}

			FillRecentShots(shots);

			_appSettings.RecentShotsList = shots.ToArray();
			_appSettings.Save();
		}

		private void OnShot(object sender, EventArgs e)
		{
			Shot();
		}

		private void Shot()
		{
			if (_isShottingStarted)
				return;

			_isShottingStarted = true;

			try
			{
				if (_imageStorage == null)
					return;

				ShotForm shotForm = new ShotForm();
				if (shotForm.ShowDialog() != DialogResult.OK || shotForm.Image == null)
				{
					return;
				}

				ImageFormat imgFormat = _appSettings.ImageFormat;
				string date = FileUtils.EscapeFilename(DateTime.Now.ToString("G"), "").Replace(".", "").Replace(' ', '_');
				string filename = string.Format("shot_{0}.{1}", date, imgFormat).ToLower();

				Image img = shotForm.Image;

				Action<ShotInfo> saveAction = s => this.Invoke((MethodInvoker)delegate
																																			{
																																				AddRecentShot(s);
																																				CompleteSaving(s.Image, s);
																																				//Configuration config = ConfigurationManager.OpenExeConfiguration(ConfigurationUserLevel.PerUserRoamingAndLocal);
																																				//MessageBox.Show(string.Format("Local user config path: {0}", config.FilePath));
																																			});

				_imageStorage.SaveImageAsync(img, imgFormat, filename, saveAction);
			}
			catch (Exception ex)
			{
				MessageBox.Show(ex.Message, Application.ProductName, MessageBoxButtons.OK, MessageBoxIcon.Error);
			}
			finally
			{
				_isShottingStarted = false;
			}
		}

		private void CompleteSaving(Image img, ShotInfo shotInfo)
		{
			if (_appSettings.CopyUrl || _appSettings.CopyImage)
			{
				//Clipboard.Clear();
				DataObject dataObject = new DataObject();
				if (_appSettings.CopyUrl) dataObject.SetText(shotInfo.Url.AbsoluteUri);
				if (_appSettings.CopyImage) dataObject.SetImage(img);
				Clipboard.SetDataObject(dataObject, true, 3, 300);
			}

			if (_appSettings.OpenInBrowser)
				OpenInViewer(shotInfo);
		}

		private void OpenInViewer(ShotInfo shotInfo)
		{
			if (_imageStorage == null)
				return;

			try
			{
				if (_imageStorage.IsShotInStorege(shotInfo))
				{
					if (!string.IsNullOrEmpty(shotInfo.Path) && shotInfo.Url.IsFile)
						Process.Start(shotInfo.Path);
					else
						Process.Start(shotInfo.Url.AbsoluteUri);
				}
			}
			catch (Exception err)
			{
				MessageBox.Show(err.Message, Application.ProductName, MessageBoxButtons.OK, MessageBoxIcon.Error);
			}
		}

		private void ShowSettings()
		{
			mnuSettings.Enabled = false;
			ClearHotkey();

			var dialog = new SettingsForm(_appSettings, _imageStorage);
			if (dialog.ShowDialog() == DialogResult.OK)
			{
				_imageStorage = CreateStorage();
			}
			
			SetupHotkey(); //в любом случае задаем хоткеи, т.к. они были стерты через ClearHotkeys

			mnuSettings.Enabled = true;
		}

		private void OnMenuExitClick(object sender, EventArgs e)
		{
			Application.Exit();
		}

		private void OnTreeIconMouseDoubleClick(object sender, MouseEventArgs e)
		{
			Shot();
		}

		private void OnMenuSettingsClick(object sender, EventArgs e)
		{
			ShowSettings();
		}

		private void OnMenuAboutClick(object sender, EventArgs e)
		{
			mnuAbout.Enabled = false;

			var dialog = new AboutBox();
			dialog.ShowDialog();

			mnuAbout.Enabled = true;
		}
	}
}